﻿/*
SINACOR - BMF&Bovespa
Arquivo: AlocacaoDireta.cs
Criado em: 14-mai-2010 17:57:04
Arquiteto Responsvel: p-dmartinelli
*/
using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Validation;
using Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum;
using Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Enum;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.Common.Exceptions;


namespace Sinacor.Servico.Bovespa.Alocacao.BusinessLogic
{
    public class AlocacaoDireta : BaseBusinessLogic
    {
        #region Atributos
        private int _erroFalhaCancelamentoAlocacao = 520013;
        private int _erroFalhaGravacaoAlocacao = 520012;
        private int _erroUsuarioSemPermissao = 520014;
        #endregion
        #region Propriedades
        public int ErroFalhaCancelamentoAlocacao
        {
            get { return _erroFalhaCancelamentoAlocacao; }
            set { _erroFalhaCancelamentoAlocacao = value; }
        }

        public int ErroFalhaGravacaoAlocacao
        {
            get { return _erroFalhaGravacaoAlocacao; }
            set { _erroFalhaGravacaoAlocacao = value; }
        }

        public int ErroUsuarioSemPermissao
        {
            get { return _erroUsuarioSemPermissao; }
            set { _erroUsuarioSemPermissao = value; }
        }
        #endregion
        #region M�todos
        /// <summary>
        /// Aloca um negocio
        /// </summary>
        /// <param name="negocio"></param>
        private void AlocarNegocioDisponivel(BusinessEntity.NegocioAlocadoDireto negocio)
        {
            if (negocio.DadosAlocacao.Direcionado == null ||
                (negocio.DadosAlocacao.Direcionado.Cliente == null ||
                 negocio.DadosAlocacao.Direcionado.DigitoVerificadorCliente == null ||
                 negocio.DadosAlocacao.Direcionado.Usuario == null
                ))
            {
                var direcionado = ObterDirecionado(negocio);

                if (direcionado != null)
                {
                    negocio.DadosAlocacao.Direcionado.Cliente = direcionado.Cliente;
                    negocio.DadosAlocacao.Direcionado.DigitoVerificadorCliente = direcionado.DigitoVerificadorCliente;
                    negocio.DadosAlocacao.Direcionado.Usuario = direcionado.Usuario;
                }

            }

            Infra.Service.Validation.BusinessRules.BusinessRulesValidator validator = new Sinacor.Infra.Service.Validation.BusinessRules.BusinessRulesValidator();
            
            BusinessLogic.BusinessRuleValidation.CamposObrigatoriosNegocioAlocadoDireto validadorCamposObrigatorios = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.CamposObrigatoriosNegocioAlocadoDireto();
            validadorCamposObrigatorios.EntityToValidate = negocio;
            
            BusinessLogic.BusinessRuleValidation.GrupoAssessoresStatusCliente validadorGrupoAssessores = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.GrupoAssessoresStatusCliente();
            validadorGrupoAssessores.EntityToValidate = negocio;
            
            BusinessLogic.BusinessRuleValidation.BloqueioCliente validadorBloqueioCliente = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.BloqueioCliente();
            validadorBloqueioCliente.EntityToValidate = negocio;
            
            BusinessLogic.BusinessRuleValidation.DigitoVerificadorCliente validadorDigitoVerificadorCliente = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.DigitoVerificadorCliente();
            validadorDigitoVerificadorCliente.EntityToValidate = negocio;

            BusinessLogic.BusinessRuleValidation.ExisteCarteira validadorExisteCarteira = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.ExisteCarteira();
            validadorExisteCarteira.EntityToValidate = negocio;
            
            BusinessLogic.BusinessRuleValidation.FaixaQuantidadeEspecificar validadorFaixaQuantidadeEspecificar = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.FaixaQuantidadeEspecificar();
            validadorFaixaQuantidadeEspecificar.EntityToValidate = negocio;
            
            BusinessLogic.BusinessRuleValidation.FaixaPercentualReducaoAcrescimo validadorFaixaPercentual = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.FaixaPercentualReducaoAcrescimo();
            validadorFaixaPercentual.EntityToValidate = negocio;

            validator.AddValidation("Obrigatorio", validadorCamposObrigatorios);
            validator.AddValidation("Status", validadorGrupoAssessores);
            validator.AddValidation("Bloqueio", validadorBloqueioCliente);
            validator.AddValidation("Digito", validadorDigitoVerificadorCliente);
            validator.AddValidation("Carteira", validadorExisteCarteira);
            validator.AddValidation("Quantidade", validadorFaixaQuantidadeEspecificar);
            validator.AddValidation("Percentual", validadorFaixaPercentual);

            validator.Validate();

            ResourceAccess.AlocacaoDireta alocacaoDireta = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.AlocacaoDireta();
            alocacaoDireta.IncluirNegocio(negocio);

            negocio.Negocio.QuantidadeCasada = negocio.Negocio.QuantidadeCasada + negocio.DadosAlocacao.QuantidadeEspecificar;

            alocacaoDireta.AlterarQuantidadeCasada(negocio);

        }

        /// <summary>
        /// Aloca varios negocios
        /// </summary>
        /// <param name="negocios"></param>
        public void AlocarNegocioDisponivel(List<BusinessEntity.NegocioAlocadoDireto> negocios)
        {
            Movimento.BusinessLogic.ControleMovimentoBolsa movimentoBolsa = new Movimento.BusinessLogic.ControleMovimentoBolsa();
            Movimento.BusinessEntity.DataMovimento datMov = new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento();
            datMov.Valor = null;
            Movimento.BusinessEntity.InformacoesMovimento infMovimentoBolsa = movimentoBolsa.ObterInformacoesMovimento(datMov);
           
            if (infMovimentoBolsa.EstadoMovimento == Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
            {
                bool instalado = (new Sinacor.Servico.Bovespa.Acesso.BusinessLogic.Acesso()).VerificarSistemaInstalado("BOL");
                if (instalado)
                {
                    Movimento.BusinessLogic.ControleMovimentoOrdens movimentoOrdens = new Sinacor.Servico.Bovespa.Movimento.BusinessLogic.ControleMovimentoOrdens();
                    Movimento.BusinessEntity.InformacoesMovimento infMovimentoOrdem = movimentoOrdens.ObterInformacoesMovimento(datMov);
                    if (infMovimentoOrdem.EstadoMovimento != Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
                        throw new BusinessException(ErroUsuarioSemPermissao);
                }

                if (AuthorizationContext.Current.CheckUserAccess("BCLRAP", AuthorizationContext.Current.UserId, AuthorizationContext.Current.CompanyId, "BOL"))
                {
                    foreach (BusinessEntity.NegocioAlocadoDireto item in negocios)
                    {
                        try
                        {
                            AlocarNegocioDisponivel(item);
                        }
                        catch (ValidationException vex)
                        {
                            throw vex;
                        }
                        catch (Exception)
                        {
                            throw new BusinessException(ErroFalhaGravacaoAlocacao);
                        }
                    }
                }
                else
                    throw new BusinessException(ErroUsuarioSemPermissao);
            }
            else
                throw new BusinessException(ErroUsuarioSemPermissao);

        }

        /// <summary>
        /// Busca os negocios j� alocados diretamente
        /// </summary>
        /// <param name="filtro"></param>
        public List<BusinessEntity.NegocioAlocadoDireto> ConsultarNegociosAlocados(BusinessEntity.Parameter.FiltroNegocio filtro)
        {

            BusinessEntity.NegocioAlocadoDireto alocadoDireto = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.NegocioAlocadoDireto();

            Infra.Service.Validation.BusinessRules.BusinessRulesValidator validator = new Sinacor.Infra.Service.Validation.BusinessRules.BusinessRulesValidator();
            BusinessLogic.BusinessRuleValidation.CamposObrigatoriosFiltroNegocio validadorCamposObrigatorios = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.CamposObrigatoriosFiltroNegocio();


            validadorCamposObrigatorios.EntityToValidate = filtro;
            validator.AddValidation("Campos", validadorCamposObrigatorios);
            validator.Validate();

            ResourceAccess.AlocacaoDireta alocacaoDireta = new ResourceAccess.AlocacaoDireta();
            return alocacaoDireta.ConsultarNegociosAlocados(filtro);

        }

        /// <summary>
        /// Busca os negocios disponiveis para aloca��o direta
        /// </summary>
        /// <param name="filtro"></param>
        public List<ManutencaoOrdens.BusinessEntity.Negocio> ConsultarNegociosDisponiveis(BusinessEntity.Parameter.FiltroNegocio filtro)
        {


            Infra.Service.Validation.BusinessRules.BusinessRulesValidator validator = new Infra.Service.Validation.BusinessRules.BusinessRulesValidator();
            BusinessLogic.BusinessRuleValidation.CamposObrigatoriosFiltroNegocio validadorCamposObrigatorios = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.CamposObrigatoriosFiltroNegocio();

            validadorCamposObrigatorios.EntityToValidate = filtro;


            validator.AddValidation("Campos", validadorCamposObrigatorios);
            validator.Validate();

            ResourceAccess.AlocacaoDireta alocacaoDireta = new ResourceAccess.AlocacaoDireta();
            return alocacaoDireta.ConsultarNegociosDisponiveis(filtro);

        }

        /// <summary>
        /// Desaloca um negocio
        /// </summary>
        /// <param name="negocio"></param>
        private void ExcluirNegocioAlocado(BusinessEntity.NegocioAlocadoDireto negocio)
        {
            ResourceAccess.AlocacaoDireta alocacaoDireta = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.AlocacaoDireta();
            alocacaoDireta.ExcluirNegocio(negocio);

            negocio.Negocio.QuantidadeCasada = negocio.Negocio.QuantidadeCasada - negocio.DadosAlocacao.QuantidadeEspecificar;
            alocacaoDireta.AlterarQuantidadeCasada(negocio);

        }

        /// <summary>
        /// Desaloca varios negocios
        /// </summary>
        /// <param name="negocios"></param>
        public void ExcluirNegocioAlocado(List<BusinessEntity.NegocioAlocadoDireto> negocios)
        {
            foreach (BusinessEntity.NegocioAlocadoDireto item in negocios)
            {
                try
                {
                    ExcluirNegocioAlocado(item);
                }
                catch (Exception)
                {
                    throw new BusinessException(ErroFalhaCancelamentoAlocacao);
                }
            }
        }

        /// <summary>
        /// Busca os dados de cliente e usu�rio direcionado
        /// </summary>
        /// <param name="negocio"></param>
        public BusinessEntity.Direcionado ObterDirecionado(BusinessEntity.NegocioAlocadoDireto negocio)
        {
            if (negocio.DadosAlocacao.Direcionado.TipoLiquidacao == null || negocio.DadosAlocacao.Direcionado.TipoLiquidacao == Alocacao.BusinessEntity.Enum.TipoLiquidacao.Custodiante)
            {
                Sinacor.Servico.Bovespa.Titulo.BusinessEntity.Titulo titulo = new Sinacor.Servico.Bovespa.Titulo.BusinessEntity.Titulo();
                titulo.Codigo = negocio.Negocio.Codigo;
                titulo.DataOrdem = negocio.Negocio.DataPregao;

                Titulo.BusinessLogic.Titulo bl = new Sinacor.Servico.Bovespa.Titulo.BusinessLogic.Titulo();
                Titulo.BusinessEntity.Titulo tituloResponse = bl.ObterTitulo(titulo);

                if (tituloResponse.TipoMercado == Titulo.BusinessEntity.Enum.TipoMercado.Vista || 
                    tituloResponse.TipoMercado == Titulo.BusinessEntity.Enum.TipoMercado.Fracionario || 
                    tituloResponse.TipoMercado == Titulo.BusinessEntity.Enum.TipoMercado.Futuro)
                {
                    if (tituloResponse.CodigoISIN.Length > 0)
                    {
                        if (tituloResponse.CodigoISIN.Substring(6, 2) != "PP")
                        {
                            ResourceAccess.AlocacaoDireta ra = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.AlocacaoDireta();
                            Alocacao.BusinessEntity.Direcionado direcionado = ra.ObterDirecionadoCustodiante(negocio);
                            if (direcionado == null)
                            {
                                direcionado = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Direcionado();
                                direcionado.Usuario = 0;
                                direcionado.Cliente = 0;
                                direcionado.DigitoVerificadorCliente = 0;
                            }
                            direcionado.TipoLiquidacao = Alocacao.BusinessEntity.Enum.TipoLiquidacao.Custodiante;
                            return direcionado;
                        }
                    }
                    return null;
                }
                else
                {
                    return null;
                }
            }
            if (negocio.DadosAlocacao.Direcionado.TipoLiquidacao == Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Enum.TipoLiquidacao.Arbitragem)
            {
                ResourceAccess.AlocacaoDireta ra = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.AlocacaoDireta();
                return ra.ObterDirecionadoArbitragem(negocio);
            }

            return null;

        }
        #endregion
    }

}